package run.siyuan.jdk.新特性;

import cn.hutool.core.util.ObjectUtil;
import lombok.*;
import org.junit.jupiter.api.Test;

import java.util.Optional;

/**
 * @author siyuan
 * @description: TODO Optional 相关操作
 * @date 2021/6/21 5:46 下午
 */
public class OptionalTest {

    /**
     * Optional 的三种构造：
     * 1. of(T value) 方法：参数不能为空，返回一个指定非null值的Optional。
     * 2. ofNullable(T value) 方法：参数可以为空，如果为非空，返回 Optional 描述的指定值，否则返回空的 Optional。
     * 3. empty()：构造一个空的 Optional 类
     */
    @Test
    public void test1() {
        Person person = new Person();
        // 1. empty() 构造一个空的 Optional 类
        Optional<Object> optional1 = Optional.empty();
        System.out.println("optional1 empty() ：" + ObjectUtil.isEmpty(optional1));
        // 2. of(T value) 方法：参数不能为空，返回一个指定非null值的Optional。
        Optional<Person> optional2 = Optional.of(person);
        System.out.println("Optional2 of() :" + optional2.get());
        try {
            Optional<String> optional3 = Optional.of(person.getName());
            System.out.println("Optional3 of1() :" + optional3.get());
        } catch (Exception e) {
            System.out.println("Optional3 of1() :" + e.getMessage());
        }
        // 3. ofNullable(T value) 方法：参数可以为空，如果为非空，返回 Optional 描述的指定值，否则返回空的 Optional。
        Optional<Integer> optional4 = Optional.ofNullable(person.getAge());
        System.out.println("Optional4 ofNullable() :" + optional4.get());
        // 4. get()：如果在这个Optional中包含这个值，返回值，否则抛出异常：NoSuchElementException
        Optional<String> optional5 = null;
        try {
            optional5 = Optional.ofNullable(person.getName());
            System.out.println("Optional5 get() :" + optional5.get());
        } catch (Exception e) {
            System.out.println("Optional5 get() :" + e.getMessage());
        }
        // 5. isPresent()：如果值存在则方法会返回true，否则返回 false。
        System.out.println("Optional5 isPresent() :" + optional5.isPresent());
        // 6. orElse(T other)：如果存在该值，返回值， 否则返回 other。
        System.out.println("Optional6 orElse() :" + optional5.orElse("orElse"));
        // 7. orElseGet(T other)：如果存在该值，返回值， 否则触发 other，并返回 other 调用的结果。
        System.out.println("Optional7 orElse() :" + optional5.orElseGet(() -> "orElseGet"));
        // 8. orElseThrow() 在有值时直接返回, 无值时抛出想要的异常.
        // 9. ifPresent(Consumer<? super T> consumer)：如果值存在则使用该值调用 consumer , 否则不做任何事情。
        optional5.ifPresent(System.out::println);
        // 10. map(Function<? super T,? extends U> mapper)：如果有值，则对其执行调用映射函数得到返回值。如果返回值不为 null，则创建包含映射返回值的Optional作为map方法返回值，否则返回空Optional。
        optional2.map(item -> {
           item.setSalary(1);
           item.setAge(1);
           item.setArea("a");
           item.setName("1");
           item.setSex("1");
           return item;
        });
        System.out.println("Optional8 map() :" + optional2.get());
        optional2.map(item -> {
            item.setSalary(1);
            item.setAge(1);
            item.setArea("a");
            return item;
        }).map(item -> {
            item.setAge(2);
            return item;
        });
        System.out.println("Optional8 map() :" + optional2.get());
        // 11. flatMap(Function<? super T,Optional<U>> mapper)：如果值存在，返回基于Optional包含的映射方法的值，否则返回一个空的Optional
//        ArrayList<Person> list = new ArrayList<>();
//        list.add(new Person("1",1,1,"1","1"));
//        list.add(new Person("2",2,2,"2","2"));
//        Optional<ArrayList<Person>> listOptional = Optional.ofNullable(list);
//        listOptional.filter(item -> {
//           item.
//        });

        // 12. filter() :如果有值并且满足条件返回包含该值的Optional，否则返回空Optional。
        Optional<String> longName = Optional.ofNullable("abcde").filter((value) -> value.length() > 6);
        System.out.println(longName.orElse("The name is less than 6 characters"));//输出Sanaulla
    }

    @Data
    @EqualsAndHashCode
    @ToString
    @AllArgsConstructor
    @NoArgsConstructor
    class Person {
        private String name;  // 姓名
        private int salary; // 薪资
        private int age; // 年龄
        private String sex; //性别
        private String area;  // 地区

    }

}
